#include "planner/optimizer_context.h"

#include <memory>

#include "planner/logical_operators.h"

namespace optimizer {

GroupExpression *OptimizerContext::MakeGroupExpression(std::shared_ptr<Operator> node) {
  std::vector<group_id_t> child_groups;
  child_groups.reserve(node->GetChildren().size());
  for (auto &&child : node->GetChildren()) {
    if (child->GetOpType() == OperatorType::LeafOperator) {
      // Special case for LeafOperator
      const auto &leaf = child->CastTo<LeafOperator>();
      auto child_group = leaf.GetOriginGroup();
      child_groups.push_back(child_group);
    } else {
      // Create a GroupExpression for the child
      auto *gexpr = MakeGroupExpression(std::shared_ptr<Operator>(child));

      // Insert into the memo (this allows for duplicate detection)
      auto *mexpr = memo_.InsertExpression(gexpr, false);
      if (mexpr == nullptr) {
        // Delete if need to (see InsertExpression spec)
        child_groups.push_back(gexpr->GetGroupID());
        delete gexpr;
      } else {
        child_groups.push_back(mexpr->GetGroupID());
      }
    }
  }
  return new GroupExpression(std::move(node), std::move(child_groups));
}

}  // namespace optimizer
